package com.mktneutral.jobs;

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxBinary;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.quartz.Job;
import org.quartz.JobExecutionContext;

public class WebLogins implements Job {
	private static FirefoxDriver webDriver;
	private static  String[] searchStrings = {"java sql", "java mongodb", "php javascript", 
		"mysql oracle", "java physics", "groovy sql", "java jquery", "node java", "box2d", "opengl java", 
		"teamcity java", "teamcity sql"};
	
	/**
	 * Time to pause and wait before proceeding to execute the next operation.
	 */
	private static int WAIT_PERIOD = 4000;
	
	/**
	 * The executor service for running the Callables.
	 */
	private static ExecutorService executor = Executors.newSingleThreadExecutor();

	/**
	 * SLF4J logger implementation.
	 * 
	 */
   private static Logger logger = LoggerFactory.getLogger(WebLogins.class);
        
   public static void main( String[] args ) {
	   webDriver = new FirefoxDriver(new FirefoxBinary(new File("/usr/bin/firefox")), 
			   new FirefoxProfile(new File("/root/.mozilla/firefox/u98v1pur.default")));

	   ArrayList<Callable> callList = new ArrayList<Callable>();
	   callList.add(new LinkedInHitter());
	   callList.add(new MyFitnessPalHitter());
	   callList.add(new TwitterHitter());
	   callList.add(new GangnamStyleHitter());
	   callList.add(new SimplyHiredHitter());
	   callList.add(new CyberCodersHitter());
	   callList.add(new IndeedHitter());

	   for ( Callable caller : callList ) {
		   doCall(caller, 30);
	   }

	   cleanTmp();

	   webDriver.close();
	   
	   System.exit(0);
   	}

    public void execute(JobExecutionContext context) {
    }
   
   	/**
   	 * The function that executes a callable and waits for it to timeout or finish.
   	 * 
   	 * @param caller  The Callable<V> to execute.
   	 * @param timeout The timeout period in seconds.
   	 */
   	public static void doCall(Callable caller, int timeout) {
    	Future<Boolean> future = executor.submit(caller);
		try {
			future.get(timeout, TimeUnit.SECONDS);
		} catch ( TimeoutException te ) {
			logger.info( te.getMessage() );
		} catch ( ExecutionException ee ) {
			logger.info( ee.getMessage() );
		} catch ( InterruptedException ie ) {
			logger.info( ie.getMessage() );
		}
   	}
   
	/**
	 * Callable class for hitting the Indeed site.
	 * 
	 * @author Jerry Vigil
	 *
	 */
   	private static class IndeedHitter implements Callable<Boolean> {
		public Boolean call() {
			String searchString = searchStrings[(new Random()).nextInt(searchStrings.length)];

			webDriver.get("http://www.indeed.com/");

			logger.info( webDriver.getPageSource() );

			WebElement whatInput = webDriver.findElementById("what");
			whatInput.sendKeys(searchString);
			try {
				(new Robot()).keyPress(KeyEvent.VK_ENTER);
			} catch ( AWTException awte ) {
				logger.info( awte.getMessage() );
			}
			 
			sleep( WAIT_PERIOD );

			logger.info( webDriver.getPageSource() );
			
			return true;
		}
	}
   	
	/**
	 * Callable class for hitting the CyberCoders site.
	 * 
	 * @author Jerry Vigil
	 *
	 */
	private static class CyberCodersHitter implements Callable<Boolean> {
		public Boolean call() {
			String searchString = searchStrings[(new Random()).nextInt(searchStrings.length)];

			webDriver.get("http://www.cybercoders.com/job-search/?l=94103&r=100&c=&s=relevance&a=0&page=");

			sleep( WAIT_PERIOD );

			logger.info( webDriver.getPageSource() );
			
			return true;
		}
	}
	
	/**
	 * Callable class for hitting the LinkedIn site.
	 * 
	 * @author Jerry Vigil
	 *
	 */
	private static class LinkedInHitter implements Callable<Boolean> {
		public Boolean call() {
			webDriver.get("https://www.linkedin.com/");

			sleep( WAIT_PERIOD );

			logger.info( webDriver.getPageSource() );
			
			return true;
		}
	}
	
	/**
	 * Callable class for hitting the SimplyHired website.
	 * 
	 * @author Jerry Vigil
	 *
	 */
	private static class SimplyHiredHitter implements Callable<Boolean> {
		public Boolean call() {
			String searchString = searchStrings[(new Random()).nextInt(searchStrings.length)];

			webDriver.get("http://www.simplyhired.com/");
			WebElement searchBox = webDriver.findElementById("f_keywords");
			searchBox.sendKeys( searchString );

			try { 
				(new Robot()).keyPress(KeyEvent.VK_ENTER);
			} catch ( AWTException awte ) {
				awte.printStackTrace();
			}

			sleep( WAIT_PERIOD );
			
			return true;
		}
	}

	/**
	 * Callable class for hitting the MyFitnesspal website.
	 * 
	 * @author Jerry Vigil
	 *
	 */
	private static class MyFitnessPalHitter implements Callable<Boolean> {
		public Boolean call() {
			webDriver.get("http://www.myfitnesspal.com/");
			sleep( WAIT_PERIOD );
			
			return true;
		}
	}
	
	/**
	 * Callable class for hitting the twitter site.
	 * 
	 * @author Jerry Vigil
	 *
	 */
	private static class TwitterHitter implements Callable<Boolean> {
		public Boolean call() {
			webDriver.get("https://twitter.com/");		
			sleep(WAIT_PERIOD);
			
			return true;
		}
	}

	public static void cleanTmp() {
		Process process = null;

		try {
			process = Runtime.getRuntime().exec("/bin/rm -rf /tmp/anonymous*");
			process.waitFor(); 
		} catch ( IOException ioe ) {
			ioe.printStackTrace();
		} catch ( InterruptedException ie ) {
			ie.printStackTrace();
		}

		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
			String s;
			while ((s = reader.readLine()) != null) {
				logger.info( s );
			}
		}  catch ( IOException ioe ) {
			ioe.printStackTrace();
		}
	}

	/**
	 * Convenience method for sleeping on a thread.
	 * 
	 * @param period  The time in milliseconds to sleep.
	 */
	public static void sleep( int period ) {
		try {
			Thread.sleep( period );
		} catch ( InterruptedException ie ) {
			ie.printStackTrace();
		}
	}
	
	/**
	 * Callable class for hitting the Gangnam Style video page on YouTube.
	 * 
	 * @author Jerry Vigil
	 *
	 */
	private static class GangnamStyleHitter implements Callable<Boolean> {
		public Boolean call() {
			webDriver.get("http://www.youtube.com/watch?v=9bZkp7q19f0");
			sleep(40000);
			
			return true;
		}
	}
}
